package com.anandsoftware.db;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.anandsoftware.db.type.DatabaseType;

public class ConnectionUtill {

	private final Logger LOG = LoggerFactory.getLogger(ConnectionUtill.class);
	private static ConnectionUtill connectionUtil = null;
	private Connection connection = null;
	private String url = "";
	private String databaseName = "";
	private String databaseClass = "";
	private String username = "";
	private String password = "";

	static {
		connectionUtil = new ConnectionUtill();
	}

	private ConnectionUtill() {
	};

	/**
	 * @return the connectionUtil
	 */
	public static ConnectionUtill getConnectionUtil() {
		return connectionUtil;
	}

	/**
	 * @return the url
	 */
	public String getUrl() {
		return url;
	}

	/**
	 * @param url
	 *            the url to set
	 */
	public void setUrl(String url) {
		this.url = url;
	}

	/**
	 * @return the databaseName
	 */
	public String getDatabaseName() {
		return databaseName;
	}

	/**
	 * @param databaseName
	 *            the databaseName to set
	 */
	public void setDatabaseName(String databaseName) {
		this.databaseName = databaseName;
	}

	/**
	 * @return the databaseClass
	 */
	public String getDatabaseClass() {
		return databaseClass;
	}

	/**
	 * @param databaseClass
	 *            the databaseClass to set
	 */
	public void setDatabaseClass(String databaseClass) {
		this.databaseClass = databaseClass;
	}

	/**
	 * @return the username
	 */
	public String getUsername() {
		return username;
	}

	/**
	 * @param username
	 *            the username to set
	 */
	public void setUsername(String username) {
		this.username = username;
	}

	/**
	 * @return the password
	 */
	public String getPassword() {
		return password;
	}

	/**
	 * @param password
	 *            the password to set
	 */
	public void setPassword(String password) {
		this.password = password;
	}

	public Connection getConnection() {
		LOG.info("Opening new Connection");
		if (connection != null) {
			return connection;
		}
		String connectionString = url + databaseName;
		try {
			Class.forName(databaseClass);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			LOG.error("Database Class can not be loaded.");
		}
		try {
			connection = DriverManager.getConnection(connectionString,
					username, password);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			LOG.error("Connection can not be opened.");
		}
		return connection;
	}

	/**
	 * 
	 * @param databaseType
	 *            DatabaseType can be mysql,oracle etc. it gives connection
	 *            accordingly.
	 * @return connection to database.
	 */
	public Connection getConnection(int databaseType) {
		LOG.info("Opening Connection With DBtype");
		switch (databaseType) {
		case DatabaseType.MYSQL:
			url = "jdbc:mysql://localhost:3306/";
			databaseClass = "com.mysql.jdbc.Driver";
			return getConnection();
		case DatabaseType.ORACLE:
			url = "jdbc:oracle:thin:@localhost:1521:";
			databaseClass = "oracle.jdbc.driver.OracleDriver";
			return getConnection();
		case DatabaseType.MICROSOFT_ACCESS:
			url = "jdbc:odbc:";
			databaseClass = "sun.jdbc.odbc.JdbcOdbcDriver";
			return getConnection();
		case DatabaseType.SQLITE:
			url = "jdbc:sqlite:";
			databaseClass = "org.sqlite.JDBC";
			return getConnection();
		default:
			return null;
		}
	}

	/**
	 * closes database connection.
	 */
	public void closeConnection() {
		try {
			connection.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			LOG.error("Can't Close connection");
		}
	}

	/**
	 * destroy this object.
	 */
	public static void destroyConnectionUtil() {
		connectionUtil.closeConnection();
		connectionUtil = null;
	}

	/**
	 * 
	 * @return new instance of this class
	 */
	public static ConnectionUtill getNewConnectionUtil() {
		return new ConnectionUtill();
	}
}
